ZF.add('plugin-switch-async', function(Z) {
    
    var P = Z.Plugin,
        D = Z.Dom,
        I = Z.IO,
        F = Z.Function,
        S = Z.String,
        J = Z.Json;

    P.SwitchableAsync = Z.create(function(superClass) {

        return {

            init : function(options) {
                var self = this, ops;

                superClass.init.call(self, options);

                ops = self.options;

                // custom url maker
                self.urlRule = ops.urlRule || F.bind(function(url) {
                    return url;
                }, self, [ops.url]);

                // custom data maker
                self.dataRule = ops.dataRule || function() { return null; };

                // custom parser
                self.parserRule = ops.parserRule || self.iParser;

                delete ops.urlRule;
                delete ops.dataRule;
                delete ops.parserRule;

                self.xhrs = {};

                // default tab has loaded
                self.xhrs[self.index] = true;

                return self;
            },
            
            iLoadTip : Z.emtyFn,
            
            iLoaded : function(index, txt) {
                var self = this;
                try {
                    self.xhrs[index] = true;
                    D.html(self.panels[index], self.parserRule(txt));
                } catch(e) {
                    return e;
                }
                return true;
            },

            iSwitchPanel : function(from, to) {
                var self = this, panels = self.panels;

                superClass.iSwitchPanel.call(self, from, to);

                if (!self.xhrs[to]) {
                    self.xhrs[to] = new I.Request({
                        url : self.urlRule(to),
                        data : self.dataRule(to),
                        charset : self.options.charset || 'utf-8',
                        method : 'get'
                    }).addEvents({
                        request : function() {
                            var html = self.iLoadTip();
                            if (html) {
                                D.html(panels[to], html);
                            }
                        },
                        complete : function(txt) {
                            var rs = self.iLoaded(to, txt);
                            if (rs !== true) {
                                self.fireEvent('loadError', [to, txt, rs]);
                            }
                        }
                    });
                }

                if (self.xhrs[to] !== true) {
                    self.xhrs[to].send();
                }
            },
            
            
            iParser : function(txt) {
                return txt || '';
            }

        };

    }, P.Switchable);

}, { requires : ['plugin-switch', 'io'] });